package ddz.logic;

import ch.qos.logback.classic.Logger;
import com.kaka.notice.annotation.Handler;
import ddz.constants.Crypto;
import ddz.constants.ErrCode;
import ddz.constants.ErrLevel;
import ddz.constants.OpCode;
import ddz.core.GameMode;
import ddz.db.dao.UserDao;
import ddz.db.entity.ItemInfo;
import ddz.db.entity.UserInfo;
import ddz.logic.game.GetBenefitHandler;
import ddz.net.ProtocolMessage;
import ddz.numerical.manager.ConfPlaceInfoManager;
import ddz.numerical.pojo.ConfPlaceInfo;
import ddz.numerical.pojo.Item;
import ddz.protos.GamePlace;
import ddz.protos.GameRecovery;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * 选择游戏场次
 */
@Handler(cmd = OpCode.cmd_select_place)
public class SelectPlaceHandler extends GetBenefitHandler {

    private static final Logger logger = (Logger) LoggerFactory.getLogger(SelectPlaceHandler.class);

    private void execute(Map<String, Object> paramMap) {
        UserInfo userInfo = (UserInfo) paramMap.get("userInfo");
        if (userInfo == null) return;
        int mode = (int) paramMap.get("mode");
        int place = (int) paramMap.get("place");

        int opcode = Integer.parseInt(OpCode.cmd_select_place);

        List<ItemInfo> userItemList = ItemUtils.parseItemList(userInfo.getItems());
        int cardCounterAmount = ItemUtils.getPropItemAmount(userItemList, 700);
        int dipaiAmount = ItemUtils.getPropItemAmount(userItemList, 9);
        if (mode == GameMode.LIAN_WIN.getId()) {
            GamePlace.ScSelectPlace.Builder builder = GamePlace.ScSelectPlace.newBuilder()
                    .setMode(mode)
                    .setPlace(place)
                    .setResult(1)
                    .setOwnedBeans(userInfo.getGold())
                    .setNeedBeans(0)
                    .setCardCounter(cardCounterAmount)
                    .setDipai(dipaiAmount)
                    .setOneRewards(0)
                    .setTenRewards(0);
            this.sendData(userInfo.getUid(), Crypto.isCrypto, opcode, builder.build().toByteArray());
            return;
        }
        ConfPlaceInfoManager confPlaceInfoManager = this.retrieveProxy(ConfPlaceInfoManager.class);
        ConfPlaceInfo confPlaceInfo = confPlaceInfoManager.getConfPlaceInfo(mode, place);
        if (confPlaceInfo == null) {
            return;
        }
        Item confOneRewards = confPlaceInfo.getGive1().get(0);
        Item confTenRewards = confPlaceInfo.getGive2().get(0);
        GamePlace.ScSelectPlace.Builder builder = GamePlace.ScSelectPlace.newBuilder()
                .setMode(mode)
                .setPlace(place)
                .setCardCounter(cardCounterAmount)
                .setDipai(dipaiAmount)
                .setOneRewards(confOneRewards.getNum())
                .setTenRewards(confTenRewards.getNum())
                .setTenRemain(UserUtils.calcTenRemain(userInfo, mode, place, confPlaceInfoManager));
        if (userInfo.getGold() >= confPlaceInfo.getMinGold()) {
            builder.setResult(1);
        } else {
            if (userInfo.getGold() > confPlaceInfo.getMaxGold()) {
                builder.setResult(3);
                builder.setOwnedBeans(userInfo.getGold());
                builder.setNeedBeans(confPlaceInfo.getMaxGold());
            } else {
                builder.setResult(2);
                builder.setOwnedBeans(userInfo.getGold());
                builder.setNeedBeans(confPlaceInfo.getMinGold());
            }
        }
        this.sendData(userInfo.getUid(), Crypto.isCrypto, opcode, builder.build().toByteArray());
    }

    @Override
    public void execute(ProtocolMessage msg) throws Exception {
        if (msg.getBody() instanceof Map) {
            Map<String, Object> paramMap = (Map<String, Object>) msg.getBody();
            this.execute(paramMap);
            return;
        }
        byte[] bytes = (byte[]) msg.getBody();
        GamePlace.CsSelectPlace csSelectPlace = GamePlace.CsSelectPlace.parseFrom(bytes);
        int mode = csSelectPlace.getMode();
        int place = csSelectPlace.getPlace();
        UserDao userDao = this.retrieveProxy(UserDao.class);
        UserInfo userInfo = userDao.getUserInfo(msg.uid());
        if (userInfo == null) {
            logger.info("玩家 [{}] 数据不存在", msg.uid());
            sendError(msg.ctx(), opcode(), ErrLevel.ERROR, ErrCode.data_err);
            return;
        }

        if(userInfo.getDeskId() > 0) {
            //已经在对局中
            byte[] reqBytes = GameRecovery.CsRecovery.newBuilder()
                    .setToken("")
                    .build().toByteArray();
            sendMessage(new ProtocolMessage(Integer.parseInt(OpCode.cmd_recovery), reqBytes, userInfo.getUid()));
            return;
        }

        int opcode = Integer.parseInt(OpCode.cmd_select_place);

        List<ItemInfo> userItemList = ItemUtils.parseItemList(userInfo.getItems());
        boolean update = ItemUtils.filterItems(userItemList);
        if (update) userDao.insertOrUpdateUser(userInfo);
        int cardCounterAmount = ItemUtils.getPropItemAmount(userItemList, 700);
        int dipaiAmount = ItemUtils.getPropItemAmount(userItemList, 9);
        if (mode == GameMode.LIAN_WIN.getId()) {
            GamePlace.ScSelectPlace.Builder builder = GamePlace.ScSelectPlace.newBuilder()
                    .setMode(mode)
                    .setPlace(place)
                    .setResult(1)
                    .setOwnedBeans(userInfo.getGold())
                    .setNeedBeans(0)
                    .setCardCounter(cardCounterAmount)
                    .setDipai(dipaiAmount)
                    .setOneRewards(0)
                    .setTenRewards(0);
            this.sendData(userInfo.getUid(), Crypto.isCrypto, opcode, builder.build().toByteArray());
            return;
        }
        ConfPlaceInfoManager confPlaceInfoManager = this.retrieveProxy(ConfPlaceInfoManager.class);
        ConfPlaceInfo confPlaceInfo = confPlaceInfoManager.getConfPlaceInfo(mode, place);
        if (confPlaceInfo == null) {
            logger.info("场次 [{}] 对应的配置数据不存在", place);
            sendError(userInfo.getUid(), opcode, ErrLevel.ERROR, ErrCode.data_err);
            return;
        }
        if (userInfo.getGold() < confPlaceInfo.getMinGold()) {
            boolean flag = this.isCanGetBenefit(userInfo, true); //此方法会发送是否需要领取救济的协议
            if (flag) {
                return;
            }
            sendError(userInfo.getUid(), opcode, ErrLevel.WARN, ErrCode.gold_not_enough);
            return;
        }
        if (userInfo.getGold() > confPlaceInfo.getMaxGold()) {
            sendError(userInfo.getUid(), opcode, ErrLevel.WARN, ErrCode.gold_beyond_max_limit);
            return;
        }
        Item confOneRewards = confPlaceInfo.getGive1().get(0);
        Item confTenRewards = confPlaceInfo.getGive2().get(0);
        GamePlace.ScSelectPlace.Builder builder = GamePlace.ScSelectPlace.newBuilder()
                .setMode(mode)
                .setPlace(place)
                .setCardCounter(cardCounterAmount)
                .setDipai(dipaiAmount)
                .setOneRewards(confOneRewards.getNum())
                .setTenRewards(confTenRewards.getNum())
                .setTenRemain(UserUtils.calcTenRemain(userInfo, mode, place, confPlaceInfoManager));
        if (userInfo.getGold() >= confPlaceInfo.getMinGold()) {
            builder.setResult(1);
        } else {
            if (userInfo.getGold() > confPlaceInfo.getMaxGold()) {
                builder.setResult(3);
                builder.setOwnedBeans(userInfo.getGold());
                builder.setNeedBeans(confPlaceInfo.getMaxGold());
            } else {
                builder.setResult(2);
                builder.setOwnedBeans(userInfo.getGold());
                builder.setNeedBeans(confPlaceInfo.getMinGold());
            }
        }
        this.sendData(userInfo.getUid(), Crypto.isCrypto, opcode, builder.build().toByteArray());
    }

}
